home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / pico / tinfo.c < prev    next >
C/C++ Source or Header  |  1996-03-15  |  15KB  |  626 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: tinfo.c,v 4.24 1996/03/15 07:41:11 hubert Exp $";
  3. #endif
  4. /*
  5.  * Program:    Display routines
  6.  *
  7.  *
  8.  * Donn Cave
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: donn@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1996 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*
  31.  *      tinfo - substitute for tcap, on systems that have terminfo.
  32.  */
  33.  
  34. #define    termdef    1            /* don't define "term" external */
  35.  
  36. #include    <stdio.h>
  37. #include        <signal.h>
  38. #include    "osdep.h"
  39. #include    "estruct.h"
  40. #include        "pico.h"
  41. #include        "edef.h"
  42.  
  43. extern char *tigetstr ();
  44.  
  45. #define    MARGIN    8
  46. #define    SCRSIZ    64
  47. #define    MROW    2
  48. #define BEL     0x07
  49. #define ESC     0x1B
  50.  
  51. extern int      ttopen();
  52. extern int      ttgetc();
  53. extern int      ttputc();
  54. extern int      ttflush();
  55. extern int      ttclose();
  56.  
  57. static int      tinfomove();
  58. static int      tinfoeeol();
  59. static int      tinfoeeop();
  60. static int      tinfobeep();
  61. static int    tinforev();
  62. static int      tinfoopen();
  63. static int      tinfoclose();
  64. static void     setup_dflt_pico_esc_seq();
  65.  
  66. extern int      tput();
  67. extern char     *tgoto();
  68.  
  69. static int      putpad();
  70.  
  71. static char *UP, PC, *CM, *CE, *CL, *SO, *SE;
  72. /* 
  73.  * PICO extentions 
  74.  */
  75. static char *DL,            /* delete line */
  76.     *AL,            /* insert line */
  77.     *CS,            /* define a scrolling region, vt100 */
  78.     *IC,            /* insert character, preferable to : */
  79.     *IM,            /* set insert mode and, */
  80.     *EI,            /* end insert mode */
  81.     *DC,            /* delete character */
  82.     *DM,            /* set delete mode and, */
  83.     *ED,            /* end delete mode */
  84.     *SF,            /* scroll text up */
  85.     *SR,            /* scroll text down */
  86.     *TI,            /* string to start termcap */
  87.         *TE;            /* string to end termcap */
  88.  
  89. TERM term = {
  90.         NROW-1,
  91.         NCOL,
  92.     MARGIN,
  93.     SCRSIZ,
  94.     MROW,
  95.         tinfoopen,
  96.         tinfoclose,
  97.         ttgetc,
  98.         ttputc,
  99.         ttflush,
  100.         tinfomove,
  101.         tinfoeeol,
  102.         tinfoeeop,
  103.         tinfobeep,
  104.         tinforev
  105. };
  106.  
  107.  
  108. /*
  109.  * Add default keypad sequences to the trie.
  110.  */
  111. static void
  112. setup_dflt_pico_esc_seq()
  113. {
  114.     /*
  115.      * this is sort of a hack [no kidding], but it allows us to use
  116.      * the function keys on pc's running telnet
  117.      */
  118.  
  119.     /* 
  120.      * UW-NDC/UCS vt10[02] application mode.
  121.      */
  122.     kpinsert(&pico_kbesc, "\033OP", F1);
  123.     kpinsert(&pico_kbesc, "\033OQ", F2);
  124.     kpinsert(&pico_kbesc, "\033OR", F3);
  125.     kpinsert(&pico_kbesc, "\033OS", F4);
  126.     kpinsert(&pico_kbesc, "\033Op", F5);
  127.     kpinsert(&pico_kbesc, "\033Oq", F6);
  128.     kpinsert(&pico_kbesc, "\033Or", F7);
  129.     kpinsert(&pico_kbesc, "\033Os", F8);
  130.     kpinsert(&pico_kbesc, "\033Ot", F9);
  131.     kpinsert(&pico_kbesc, "\033Ou", F10);
  132.     kpinsert(&pico_kbesc, "\033Ov", F11);
  133.     kpinsert(&pico_kbesc, "\033Ow", F12);
  134.  
  135.     /*
  136.      * DEC vt100, ANSI and cursor key mode.
  137.      */
  138.     kpinsert(&pico_kbesc, "\033OA", K_PAD_UP);
  139.     kpinsert(&pico_kbesc, "\033OB", K_PAD_DOWN);
  140.     kpinsert(&pico_kbesc, "\033OC", K_PAD_RIGHT);
  141.     kpinsert(&pico_kbesc, "\033OD", K_PAD_LEFT);
  142.  
  143.     /*
  144.      * special keypad functions
  145.      */
  146.     kpinsert(&pico_kbesc, "\033[4J", K_PAD_PREVPAGE);
  147.     kpinsert(&pico_kbesc, "\033[3J", K_PAD_NEXTPAGE);
  148.     kpinsert(&pico_kbesc, "\033[2J", K_PAD_HOME);
  149.     kpinsert(&pico_kbesc, "\033[N",  K_PAD_END);
  150.  
  151.     /* 
  152.      * ANSI mode.
  153.      */
  154.     kpinsert(&pico_kbesc, "\033[=a", F1);
  155.     kpinsert(&pico_kbesc, "\033[=b", F2);
  156.     kpinsert(&pico_kbesc, "\033[=c", F3);
  157.     kpinsert(&pico_kbesc, "\033[=d", F4);
  158.     kpinsert(&pico_kbesc, "\033[=e", F5);
  159.     kpinsert(&pico_kbesc, "\033[=f", F6);
  160.     kpinsert(&pico_kbesc, "\033[=g", F7);
  161.     kpinsert(&pico_kbesc, "\033[=h", F8);
  162.     kpinsert(&pico_kbesc, "\033[=i", F9);
  163.     kpinsert(&pico_kbesc, "\033[=j", F10);
  164.     kpinsert(&pico_kbesc, "\033[=k", F11);
  165.     kpinsert(&pico_kbesc, "\033[=l", F12);
  166.  
  167.     /*
  168.      * DEC vt100, ANSI and cursor key mode reset.
  169.      */
  170.     kpinsert(&pico_kbesc, "\033[A", K_PAD_UP);
  171.     kpinsert(&pico_kbesc, "\033[B", K_PAD_DOWN);
  172.     kpinsert(&pico_kbesc, "\033[C", K_PAD_RIGHT);
  173.     kpinsert(&pico_kbesc, "\033[D", K_PAD_LEFT);
  174.  
  175.     /*
  176.      * DEC vt52 mode.
  177.      */
  178.     kpinsert(&pico_kbesc, "\033A", K_PAD_UP);
  179.     kpinsert(&pico_kbesc, "\033B", K_PAD_DOWN);
  180.     kpinsert(&pico_kbesc, "\033C", K_PAD_RIGHT);
  181.     kpinsert(&pico_kbesc, "\033D", K_PAD_LEFT);
  182.  
  183.     /*
  184.      * DEC vt52 application keys, and some Zenith 19.
  185.      */
  186.     kpinsert(&pico_kbesc, "\033?r", K_PAD_DOWN);
  187.     kpinsert(&pico_kbesc, "\033?t", K_PAD_LEFT);
  188.     kpinsert(&pico_kbesc, "\033?v", K_PAD_RIGHT);
  189.     kpinsert(&pico_kbesc, "\033?x", K_PAD_UP);
  190.  
  191.     /*
  192.      * Sun Console sequences.
  193.      */
  194.     kpinsert(&pico_kbesc, "\033[1",   K_SWALLOW_TIL_Z);
  195.     kpinsert(&pico_kbesc, "\033[215", K_SWALLOW_UP);
  196.     kpinsert(&pico_kbesc, "\033[217", K_SWALLOW_LEFT);
  197.     kpinsert(&pico_kbesc, "\033[219", K_SWALLOW_RIGHT);
  198.     kpinsert(&pico_kbesc, "\033[221", K_SWALLOW_DOWN);
  199.  
  200.     /*
  201.      * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
  202.      */
  203.     kpinsert(&pico_kbesc, "\033_", K_KERMIT);
  204.  
  205.     /*
  206.      * Fake a control character.
  207.      */
  208.     kpinsert(&pico_kbesc, "\033\033", K_DOUBLE_ESC);
  209. }
  210.  
  211.  
  212. static tinfoopen()
  213. {
  214.     char  *t;
  215.     char  *getenv();
  216.     int    row, col;
  217.     char  *KU, *KD, *KL, *KR,
  218.       *KPPU, *KPPD, *KPHOME, *KPEND, *KPDEL,
  219.       *KF1, *KF2, *KF3, *KF4, *KF5, *KF6,
  220.       *KF7, *KF8, *KF9, *KF10, *KF11, *KF12;
  221.  
  222.  
  223.     /*
  224.      * determine the terminal's communication speed and decide
  225.      * if we need to do optimization ...
  226.      */
  227.     optimize = ttisslow();
  228.  
  229.     if (Pmaster) {
  230.     /*
  231.      *        setupterm() automatically retrieves the value
  232.      *        of the TERM variable.
  233.      */
  234.     int err;
  235.     setupterm (0, 1, &err);
  236.     if (err != 1) return FALSE;
  237.     }
  238.     else {
  239.     /*
  240.      *        setupterm() issues a message and exits, if the
  241.      *        terminfo data base is gone or the term type is
  242.      *        unknown, if arg2 is 0.
  243.      */
  244.     setupterm (0, 1, 0);
  245.     }
  246.  
  247.     t = tigetstr("pad");
  248.     if(t)
  249.       PC = *t;
  250.  
  251.     CL = tigetstr("clear");
  252.     CM = tigetstr("cup");
  253.     CE = tigetstr("el");
  254.     UP = tigetstr("cuu1");
  255.     SE = tigetstr("rmso");
  256.     SO = tigetstr("smso");
  257.     DL = tigetstr("dl1");
  258.     AL = tigetstr("il1");
  259.     CS = tigetstr("csr");
  260.     IC = tigetstr("ich1");
  261.     IM = tigetstr("smir");
  262.     EI = tigetstr("rmir");
  263.     DC = tigetstr("dch1");
  264.     DM = tigetstr("smdc");
  265.     ED = tigetstr("rmdc");
  266.     SF = tigetstr("ind");
  267.     SR = tigetstr("ri");
  268.     TI = tigetstr("smcup");
  269.     TE = tigetstr("rmcup");
  270.  
  271.     row = tigetnum("lines");
  272.     if(row == -1){
  273.     char *er;
  274.     int   rr;
  275.  
  276.     /* tigetnum failed, try $LINES */
  277.     er = getenv("LINES");
  278.     if(er && (rr = atoi(er)) > 0)
  279.       row = rr;
  280.     }
  281.     if(row >= 0)
  282.       row--;
  283.  
  284.     col = tigetnum("cols");
  285.     if(col == -1){
  286.     char *ec;
  287.     int   cc;
  288.  
  289.     /* tigetnum failed, try $COLUMNS */
  290.     ec = getenv("COLUMNS");
  291.     if(ec && (cc = atoi(ec)) > 0)
  292.       col = cc;
  293.     }
  294.     
  295.     ttgetwinsz(&row, &col);
  296.     term.t_nrow = (short) row;
  297.     term.t_ncol = (short) col;
  298.  
  299.     eolexist = (CE != NULL);    /* will we be able to use clear to EOL? */
  300.     revexist = (SO != NULL);    /* will be able to use reverse video */
  301.     if(DC == NULL && (DM == NULL || ED == NULL))
  302.       delchar = FALSE;
  303.     if(IC == NULL && (IM == NULL || EI == NULL))
  304.       inschar = FALSE;
  305.     if((CS==NULL || SF==NULL || SR==NULL) && (DL==NULL || AL==NULL))
  306.       scrollexist = FALSE;
  307.  
  308.     if(CL == NULL || CM == NULL || UP == NULL){
  309.     if(Pmaster == NULL){
  310.         puts("Incomplete terminfo entry\n");
  311.         exit(1);
  312.     }
  313.     }
  314.     else{
  315.     KPPU   = tigetstr("kpp");
  316.     KPPD   = tigetstr("knp");
  317.     KPHOME = tigetstr("khome");
  318.     KPEND  = tigetstr("kend");
  319.     KPDEL  = tigetstr("kdch1");
  320.     KU = tigetstr("kcuu1");
  321.     KD = tigetstr("kcud1");
  322.     KL = tigetstr("kcub1");
  323.     KR = tigetstr("kcuf1");
  324.     KF1 = tigetstr("kf1");
  325.     KF2 = tigetstr("kf2");
  326.     KF3 = tigetstr("kf3");
  327.     KF4 = tigetstr("kf4");
  328.     KF5 = tigetstr("kf5");
  329.     KF6 = tigetstr("kf6");
  330.     KF7 = tigetstr("kf7");
  331.     KF8 = tigetstr("kf8");
  332.     KF9 = tigetstr("kf9");
  333.     KF10 = tigetstr("kf10");
  334.     KF11 = tigetstr("kf11");
  335.     KF12 = tigetstr("kf12");
  336.  
  337. #ifndef TERMCAP_WINS
  338.     /*
  339.      * Add default keypad sequences to the trie.
  340.      * Since these come first, they will override any conflicting termcap
  341.      * or terminfo escape sequences defined below.  An escape sequence is
  342.      * considered conflicting if one is a prefix of the other.
  343.      * So, without TERMCAP_WINS, there will likely be some termcap/terminfo
  344.      * escape sequences that don't work, because they conflict with default
  345.      * sequences.
  346.      */
  347.     setup_dflt_pico_esc_seq();
  348. #endif /* !TERMCAP_WINS */
  349.  
  350.     /*
  351.      * add terminfo escape sequences to the trie...
  352.      */
  353.     if(KU != NULL && (KL != NULL && (KR != NULL && KD != NULL))){
  354.         kpinsert(&pico_kbesc, KU, K_PAD_UP);
  355.         kpinsert(&pico_kbesc, KD, K_PAD_DOWN);
  356.         kpinsert(&pico_kbesc, KL, K_PAD_LEFT);
  357.         kpinsert(&pico_kbesc, KR, K_PAD_RIGHT);
  358.     }
  359.  
  360.     if(KPPU != NULL && KPPD != NULL){
  361.         kpinsert(&pico_kbesc, KPPU, K_PAD_PREVPAGE);
  362.         kpinsert(&pico_kbesc, KPPD, K_PAD_NEXTPAGE);
  363.     }
  364.  
  365.     kpinsert(&pico_kbesc, KPHOME, K_PAD_HOME);
  366.     kpinsert(&pico_kbesc, KPEND,  K_PAD_END);
  367.     kpinsert(&pico_kbesc, KPDEL,  K_PAD_DELETE);
  368.  
  369.     kpinsert(&pico_kbesc, KF1,  F1);
  370.     kpinsert(&pico_kbesc, KF2,  F2);
  371.     kpinsert(&pico_kbesc, KF3,  F3);
  372.     kpinsert(&pico_kbesc, KF4,  F4);
  373.     kpinsert(&pico_kbesc, KF5,  F5);
  374.     kpinsert(&pico_kbesc, KF6,  F6);
  375.     kpinsert(&pico_kbesc, KF7,  F7);
  376.     kpinsert(&pico_kbesc, KF8,  F8);
  377.     kpinsert(&pico_kbesc, KF9,  F9);
  378.     kpinsert(&pico_kbesc, KF10, F10);
  379.     kpinsert(&pico_kbesc, KF11, F11);
  380.     kpinsert(&pico_kbesc, KF12, F12);
  381.     }
  382.  
  383.     /*
  384.      * Initialize UW-modified NCSA telnet to use its functionkeys
  385.      */
  386.     if(gmode&MDFKEY && Pmaster == NULL)
  387.       puts("\033[99h");
  388.  
  389. #ifdef TERMCAP_WINS
  390.     /*
  391.      * Add default keypad sequences to the trie.
  392.      * Since these come after the termcap/terminfo escape sequences above,
  393.      * the termcap/info sequences will override any conflicting default
  394.      * escape sequences defined here.
  395.      * So, with TERMCAP_WINS, some of the default sequences will be missing.
  396.      * This means that you'd better get all of your termcap/terminfo entries
  397.      * correct if you define TERMCAP_WINS.
  398.      */
  399.     setup_dflt_pico_esc_seq();
  400. #endif /* TERMCAP_WINS */
  401.  
  402.     ttopen();
  403.  
  404.     if(TI && !Pmaster){
  405.     putpad(TI);            /* any init terminfo requires */
  406.     if(CS)
  407.       putpad(tgoto(CS, term.t_nrow, 0));
  408.     }
  409. }
  410.  
  411.  
  412. static tinfoclose()
  413. {
  414.     if(!Pmaster){
  415.     if(gmode&MDFKEY)
  416.       puts("\033[99l");        /* reset UW-NCSA telnet keys */
  417.  
  418.     if(TE)                /* any clean up terminfo requires */
  419.       putpad(TE);
  420.     }
  421.  
  422.     kbdestroy(pico_kbesc);        /* clean up key board sequence trie */
  423.     pico_kbesc = NULL;
  424.     ttclose();
  425. }
  426.  
  427.  
  428. /*
  429.  * tinfoinsert - insert a character at the current character position.
  430.  *               IC takes precedence.
  431.  */
  432. tinfoinsert(ch)
  433. register char    ch;
  434. {
  435.     if(IC != NULL){
  436.     putpad(IC);
  437.     ttputc(ch);
  438.     }
  439.     else{
  440.     putpad(IM);
  441.     ttputc(ch);
  442.     putpad(EI);
  443.     }
  444. }
  445.  
  446.  
  447. /*
  448.  * tinfodelete - delete a character at the current character position.
  449.  */
  450. tinfodelete()
  451. {
  452.     if(DM == NULL && ED == NULL)
  453.       putpad(DC);
  454.     else{
  455.     putpad(DM);
  456.     putpad(DC);
  457.     putpad(ED);
  458.     }
  459. }
  460.  
  461.  
  462. /*
  463.  * o_scrolldown() - open a line at the given row position.
  464.  *               use either region scrolling or deleteline/insertline
  465.  *               to open a new line.
  466.  */
  467. o_scrolldown(row, n)
  468. register int row;
  469. register int n;
  470. {
  471.     register int i;
  472.  
  473.     if(CS != NULL){
  474.     putpad(tgoto(CS, term.t_nrow - (term.t_mrow+1), row));
  475.     tinfomove(row, 0);
  476.     for(i = 0; i < n; i++)
  477.       putpad( (SR != NULL && *SR != '\0') ? SR : "\n" );
  478.     putpad(tgoto(CS, term.t_nrow, 0));
  479.     tinfomove(row, 0);
  480.     }
  481.     else{
  482.     /*
  483.      * this code causes a jiggly motion of the keymenu when scrolling
  484.      */
  485.     for(i = 0; i < n; i++){
  486.         tinfomove(term.t_nrow - (term.t_mrow+1), 0);
  487.         putpad(DL);
  488.         tinfomove(row, 0);
  489.         putpad(AL);
  490.     }
  491. #ifdef    NOWIGGLYLINES
  492.     /*
  493.      * this code causes a sweeping motion up and down the display
  494.      */
  495.     tinfomove(term.t_nrow - term.t_mrow - n, 0);
  496.     for(i = 0; i < n; i++)
  497.       putpad(DL);
  498.     tinfomove(row, 0);
  499.     for(i = 0; i < n; i++)
  500.       putpad(AL);
  501. #endif
  502.     }
  503. }
  504.  
  505.  
  506. /*
  507.  * o_scrollup() - open a line at the given row position.
  508.  *               use either region scrolling or deleteline/insertline
  509.  *               to open a new line.
  510.  */
  511. o_scrollup(row, n)
  512. register int row;
  513. register int n;
  514. {
  515.     register int i;
  516.  
  517.     if(CS != NULL){
  518.     putpad(tgoto(CS, term.t_nrow - (term.t_mrow+1), row));
  519.     /* setting scrolling region moves cursor to home */
  520.     tinfomove(term.t_nrow-(term.t_mrow+1), 0);
  521.     for(i = 0;i < n; i++)
  522.       putpad((SF == NULL || SF[0] == '\0') ? "\n" : SF);
  523.     putpad(tgoto(CS, term.t_nrow, 0));
  524.     tinfomove(2, 0);
  525.     }
  526.     else{
  527.     for(i = 0; i < n; i++){
  528.         tinfomove(row, 0);
  529.         putpad(DL);
  530.         tinfomove(term.t_nrow - (term.t_mrow+1), 0);
  531.         putpad(AL);
  532.     }
  533. #ifdef  NOWIGGLYLINES
  534.     /* see note above */
  535.     tinfomove(row, 0);
  536.     for(i = 0; i < n; i++)
  537.       putpad(DL);
  538.     tinfomove(term.t_nrow - term.t_mrow - n, 0);
  539.     for(i = 0;i < n; i++)
  540.       putpad(AL);
  541. #endif
  542.     }
  543. }
  544.  
  545.  
  546.  
  547. /*
  548.  * o_insert - use terminfo to optimized character insert
  549.  *            returns: true if it optimized output, false otherwise
  550.  */
  551. o_insert(c)
  552. char c;
  553. {
  554.     if(inschar){
  555.     tinfoinsert(c);
  556.     return(1);            /* no problems! */
  557.     }
  558.  
  559.     return(0);                /* can't do it. */
  560. }
  561.  
  562.  
  563. /*
  564.  * o_delete - use terminfo to optimized character insert
  565.  *            returns true if it optimized output, false otherwise
  566.  */
  567. o_delete()
  568. {
  569.     if(delchar){
  570.     tinfodelete();
  571.     return(1);            /* deleted, no problem! */
  572.     }
  573.  
  574.     return(0);                /* no dice. */
  575. }
  576.  
  577.  
  578. static tinfomove(row, col)
  579. register int row, col;
  580. {
  581.     putpad(tgoto(CM, col, row));
  582. }
  583.  
  584.  
  585. static tinfoeeol()
  586. {
  587.     putpad(CE);
  588. }
  589.  
  590.  
  591. static tinfoeeop()
  592. {
  593.         putpad(CL);
  594. }
  595.  
  596.  
  597. static tinforev(state)        /* change reverse video status */
  598. int state;                    /* FALSE = normal video, TRUE = rev video */
  599. {
  600.     static int cstate = FALSE;
  601.  
  602.     if(state == cstate)        /* no op if already set! */
  603.       return(0);
  604.  
  605.     if(cstate = state){        /* remember last setting */
  606.     if (SO != NULL)
  607.       putpad(SO);
  608.     } else {
  609.     if (SE != NULL)
  610.       putpad(SE);
  611.     }
  612. }
  613.  
  614.  
  615. static tinfobeep()
  616. {
  617.     ttputc(BEL);
  618. }
  619.  
  620.  
  621. static putpad(str)
  622. char    *str;
  623. {
  624.     tputs(str, 1, ttputc);
  625. }
  626.